package com.simplesoftwares.client.library.appstructure;

import java.util.ArrayList;

import javax.swing.JOptionPane;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.InlineLabel;
import com.simplesoftwares.client.library.ReturnFromServer;
import com.simplesoftwares.client.library.appskeleton.AppMemory;
import com.simplesoftwares.client.library.appstructure.search.MyQuerry;
import com.simplesoftwares.client.library.libservice.GenricService;
import com.simplesoftwares.client.library.libservice.GenricServiceAsync;


/**
 * Entity presenter class handels all the crude on data in an entity independent way maintaining the flow.
 * This is an mvc style controler at.The concrete implementations can choose to implement it as mvc or mvp.
 * @author Kamala
 *
 * @param <T>
 */
public abstract class EntityPresenter<T extends SuperModel> implements ClickHandler {
	
	/**
	 * Refrence of view
	 * @author Kamala
	 */
	protected UiScreen<T> view;
	/**
	 * Refrence of model
	 */
	protected T model;
	/**
	 * Refernce of Appmemory
	 */
	protected AppMemory mem;
	/**
	 * The service corresponding to current presenter.Presenter acess the save ,delete ,search methods
	 * through this service
	 */
	protected GenricServiceAsync service=GWT.create(GenricService.class);
	
	/**
	 * Initializes the presenter
	 * @param view
	 * @param model
	 */
	
	public EntityPresenter(UiScreen<T> view,T model)
	{
		this.view=view;
		this.model=model;
		//Set Presenter
		view.setPresenter(this);
		mem=AppMemory.getAppMemory();
		setEventHandeling();
		if(view.getSearchpopupscreen()!=null)
			view.getSearchpopupscreen().applyHandler(this);
		
	}

////////////////////////////////////////////ABSTRACT METHODS//////////////////////////////////////
	/**
	 * This method is responsible for saving the entity.
	 * To Do : make this non abstract as per pradnya
	 */
	protected abstract void reactOnSave();
	/**
	 * Crucial method only concrete classes will provide the implementation.This is the 
	 * only point in this flow where buisness logic will be managed.
	 * 
	 */
	
	public abstract void reactToProcessBarEvents(ClickEvent e);
	/**
	 * Method which DownLoads any Table with header
	 */
	
	public  void reactOnDownload()
	{
		
	}
	
	/**
	 * Abstract method which will be called when user click print in app level menu
	 */
	
	public abstract void reactOnPrint();
	/**
	 * Abstract method which will be called when user click email in app level menu
	 */
	
	public abstract void reactOnEmail();
	/**
	 * Abstract method which reinitalizes the mmodel.
	 */
	
	protected  abstract void makeNewModel();	
	
//////////////////////////////VALIDATE AND UPDATE THE MODEL/////////////////////////////////////////	
	/**
	 * This method first validates the view.If validation is true then it fills the corresponding data
	 * in model.
	 */
	protected boolean validateAndUpdateModel()
	{
		if(view.validate()==false)
				return false;
		
		view.updateModel(model);
		System.out.println("ID OF MODEL"+model.getId());
		    return true;
	}
	
//////////////////////////////SETTING HANDLERS ON APPHEADERMENUS & PROCESSLEVEL MENUS///////////////////////////////
	
	/**
	 * The method sets the click handler.On the app level menus.
	 * 
	 * 
	 */
	
	protected void setEventHandeling()
	  {
		
		
		for(int k=0;k<mem.skeleton.menuLabels.length;k++)
		  {
			 if( mem.skeleton.registration[k]!=null)
				 		mem.skeleton.registration[k].removeHandler();
		  }
		 
		  for( int k=0;k<mem.skeleton.menuLabels.length;k++)
		  
			 mem.skeleton.registration[k]= mem.skeleton.menuLabels[k].addClickHandler(this);	  
	  
	  
		  //Applying event handler to Process Level Bar
		  if(view.getProcessLevelBar()!=null)
		  {
		  InlineLabel[]lbl=view.getProcessLevelBar().btnLabels;
		  
		  for(int k=0;k<lbl.length;k++)
		  {
			  lbl[k].addClickHandler(this);
			  
		  }
		  }
	  
	  }

///////////////////////////////////////REGULAR METHODS///////////////////////////////////////
	
	/**
	 * Fascilates transition to home screen.
	 */
	public void reactOnDiscard()	//DISCARD
	{
		mem.goToHome();
	}
	
	/**
	 * Fascilates transition to edit state.
	 */

	public void reactOnEdit()	//EDIT
	{
		view.setToEditState();
	}
	
	/**
	 * Shows the search pop up screen
	 */
	
	public void reactOnSearch() 	//SEARCH
	{
		if(view.getSearchpopupscreen()!=null)
		   view.getSearchpopupscreen().showPopUp();
		
	}
	
	/**
	 * Delets the entity
	 * To Do : Pradnya approch needed to be utilized
	 */
	
	public void reactOnDelete()		//DELETE
	{
		view.showWaitSymbol();
		//make model deleted
		model.setDeleted(true);
		service.delete(model, new AsyncCallback<Void>() {

			@Override
			public void onFailure(Throwable caught) {
				System.out.println("Failed");
				
			}

			@Override
			public void onSuccess(Void result) {
				view.hideWaitSymbol();
				view.clear();
				makeNewModel();
				view.setToNewState();
				
				System.out.println("Sucess!!");
				
			}
		});
		
	}
	
	/**
	 * Retrives the results from server using querry object formed as per search criteria.
	 */
	
	protected void reactOnGo()		//GO
	{
		MyQuerry querry=view.getSearchpopupscreen().getQuerry();
		view.getSearchpopupscreen().getSupertable().connectToLocal();
		service.getSearchResult(querry,new AsyncCallback<ArrayList<SuperModel>>() {
			
			@SuppressWarnings("unchecked")
			@Override
			public void onSuccess(ArrayList<SuperModel> result) {
				if(result.size()==0)
					view.showDialogMessage("No Result To Display !");
				
				for(SuperModel model:result)
				{
					view.getSearchpopupscreen().getSupertable().getListDataProvider().getList().add((T) model);
				    //Set the row count of table as per the recieved data length
					
					
				
				}
				view.getSearchpopupscreen().getSupertable().getTable().setRowCount(result.size());
	}
			
			@Override
			public void onFailure(Throwable caught) {
			caught.printStackTrace();
				view.showDialogMessage("Failed To Retrive Search Result!");
			}
		});
		
	}

/////////////////////////////////////////////////CLICK EVENT//////////////////////////////////////
	@Override
	public void onClick(ClickEvent event) {
		
		if(event.getSource() instanceof InlineLabel)
		{
		InlineLabel lbl= (InlineLabel) event.getSource();
		
		if(lbl.getText().equals("Save"))
			reactOnSave();
		else if(lbl.getText().equals("Edit"))
			reactOnEdit();
		else if(lbl.getText().equals("Print"))
		   reactOnPrint();
		
		else if(lbl.getText().equals("Search"))	
			  reactOnSearch();
		
		else if(lbl.getText().equals("Go"))
		{
			
			reactOnGo();
		}
		
		else if(lbl.getText().equals("Download"))
		{
			
			reactOnDownload();
		}
		else if(lbl.getText().equals("Discard"))
		{
			
			reactOnDiscard();
		}
		else
			reactToProcessBarEvents(event);
		}
	}
		
	
//////////////////////////////////////////////GETTER SETTERS////////////////////////////////////////////////
	
	public SuperModel getModel()
	{
		return model;
	}
	
	public ViewContainer getView() {
		return view;
	}

	public void setView(UiScreen<T> view) {
		this.view = view;
	}

	public GenricServiceAsync getService() {
		return service;
	}

	public void setService(GenricServiceAsync service) {
		this.service = service;
	}

	public  void setModel(T model)
	{
		this.model=model;
	}

	
	
	
}
